Managed code platforms can present a machine-independent and architecture-neutral operating environment, such as provided by the Java operating environment, which is described in P. van der Linden, “Not Just Java,” Ch. 3, Sun Microsystems, Inc. (1997), the disclosure of which is incorporated by reference. Managed code environments are capable of providing real time execution, but ensuring such execution can be problematic due to the unpredictable latencies introduced by garbage collection mechanisms. Real time threads must be guaranteed to proceed within fixed timeliness constraints, yet other concurrent threads, particularly garbage collection threads, can potentially cause execution interference or memory corruption, absent appropriate programmatic safeguards.
Real time execution is supported in the Java operating environment, as specified in the Real-Time Specification for Java (RTSJ). Under the RTSJ, two classes of real time threads, real time (RT) threads and no-heap real time (NHRT) threads, are defined, in addition to the normal class of threads specified by the Java programming language. NHRT threads carry out execution in either immortal or scoped memory areas, which are both subject to storage reclamation that is controlled under well-defined rules not under garbage collection control. RT threads additionally carry out execution in heap storage and can assign references to heap-defined objects into objects allocated in the scoped memory area.
Garbage collection proceeds under mutual exclusion with all normal and RT threads, but is subject to preemption by NHRT threads. Storage objects allocated in a scoped memory area can only be reclaimed in the interval between inactive and active states, termed the dead zone, when the number of threads operating on the scoped memory area drops to zero.
Garbage collection preemption can create two particularized issues, where a linear garbage collection scan of a scoped memory area is temporarily interrupted. An unsynchronized read of the thread counter is sufficient to identify inactive scoped memory area, even if the counter value changes while being read by the garbage collector thread. If the thread counter value read is consistent, that is, no concurrent changes occurred, the garbage collector thread can safely proceed. However, if the thread counter value was changed during the read, two issues may arise. First, if a non-zero value was decreased to zero, the garbage collector thread will erroneously consider the scoped memory area active and perform a scan, even though performing such a scan is unnecessary and inefficient, as the scoped memory area has become inactive. Second, if a zero value was increased, the garbage collector thread will erroneously consider the scoped memory area inactive and not perform a scan. Although, strictly speaking, not problematic, updated references to heap objects relocated by the garbage collector thread will be written into the scoped memory area.
Two further problems could occur in a multiprocessing environment in which garbage collection executes on a processor distinct from one or more concurrently executing NHRT threads. Such actions could result in execution errors, memory corruption, or system crash. A similar set of problems could also occur in a uniprocessing environment. First, a scoped memory area could enter a dead zone during a garbage collection scan due to preemption. Ideally, garbage collection on that scoped memory area should stop because all stored objects are “dead” and further processing would be inefficient. Second, the NHRT threads could overrun the preempted garbage collector thread and allocate objects past the current position of the garbage collector thread. Once restarted, the garbage collector thread could incorrectly overwrite any scoped memory area locations previously interpreted as storing heap object references or could incorrectly interpret previously-read values at now-overwritten scoped memory area locations as class descriptor pointers or heap object references.
Therefore, there is a need for an approach to preventing program error and failures and memory corruption without introducing interferences to real time threads and, in particular, to NHRT threads, due to concurrent garbage collection activities.